const messageListeners = [];
const openListeners = [];
const errorListeners = [];
const closeListeners = [];
const validateListeners = [];
const chat = {
  getDomain: function () {
    return process.env.IM_API_URL;
  },
  getApiUrl: function (method) {
    return this.getDomain() + "api/v1/" + method;
  },
  init: function (token) {
    this.user = {};
    this.token = token;
    this.validate();
  },
  my: function () {
    return this.user;
  },
  agent: function () {
    return this.agentInfo;
  },
  cs: function () {
    if ('robot' === this.cva.lastCs.customerType.value) return null;
    return this.cva.lastCs;
  },
  setCs: function (cs) {
    if (this.cva) {
      this.cva.lastCs = cs;
    }
  },
  validate: function () {
    let _self = this;
    this.ajax_post_json_request({
      method: 'validate',
      token: this.token
    }, (json) => {
      if (json.status) {
        _self.user = {
          userId: json.data.userId,
          userName: json.data.name,
          userLogo: json.data.logo,
          agentId: json.data.agentId,
          onlineStatus: json.data.status.value,
          customer: 'message' === json.data.customerType.value || 'order' === json.data.customerType.value
        };
        _self.agentInfo = json.agent;
        _self.agentInfo.robot = json.robot;
        _self.server = json.wss;
        _self.cva = json.cva;
        if (_self.user.customer || _self.cs()) {
          _self.doConnect();
        }
        if (json.token && json.token.authkey && json.token.sessionid) {
          localStorage.setItem("authkey", json.token.authkey);
          localStorage.setItem("sessionid", json.token.sessionid);
        }
      } else {
        _self.callbackError(json);
      }
      _self.validateCallback(json);
    }, function (err) {
      _self.callbackError({
        message: "无法与服务器通信，请查检网络！"
      });
    });
  },
  doConnect: function () {
    let _self = this;
    if (!_self.ws) {
      this.connect();
      _self.timer = setInterval(function () {
        if (_self.ws) {
          _self.ws.send("0");
          if (3 === parseInt(_self.ws.readyState)) {
            console.warn("checking status :" + _self.ws.readyState);
            _self.connect();
          }
        } else {
          _self.connect();
        }
      }, 25000);
    }
  },
  connect: function () {
    if ('WebSocket' in window) {
      this.ws = new WebSocket(this.server + "?token=" + encodeURIComponent(this.token));
    } else if ('MozWebSocket' in window) {
      this.ws = new MozWebSocket(this.server + "?token=" + encodeURIComponent(this.token));
    }
    this.ws.addEventListener("open", this.socketOpen);
    this.ws.addEventListener("message", this.socketMessage);
    this.ws.addEventListener("close", this.socketClose);
  },
  close: function () {
    if (this.ws) {
      clearInterval(this.timer);
      this.ws.close();
    }
    this.ws = null;
  },
  socketOpen: function (event) {
    for (let i = 0; i < openListeners.length; i++) {
      openListeners[i](event);
    }
  },

  socketMessage: function (event) {
    if (event.data !== '1') {
      for (let i = 0; i < messageListeners.length; i++) {
        messageListeners[i](event);
      }
    }
  },

  callbackError: function (data) {
    console.error(data);
    for (let i = 0; i < errorListeners.length; i++) {
      errorListeners[i](data);
    }
  },

  socketClose: function (event) {
    console.error(event);
    for (let i = 0; i < closeListeners.length; i++) {
      closeListeners[i](event);
    }
    clearInterval(this.timer);
  },
  validateCallback: function (json) {
    for (let i = 0; i < validateListeners.length; i++) {
      validateListeners[i](json);
    }
  },
  addMessageListener: function (listener) {
    messageListeners.push(listener);
  },

  addSocketOpenListener: function (listener) {
    openListeners.push(listener);
  },

  addErrorListener: function (listener) {
    errorListeners.push(listener);
  },

  addSocketCloseListener: function (listener) {
    closeListeners.push(listener);
  },
  addValidateListener: function (listener) {
    validateListeners.push(listener);
  },
  sendMessage: function (content, toId, type, event, cvaId) {
    if (this.ws && 1 === parseInt(this.ws.readyState)) {
      let msg = {
        content: content,
        from: this.userId,
        to: toId,
        agentId: this.agentId,
        type: type,
        event: event,
        cvaId: cvaId ? cvaId : this.cva.cvaId,
        id: 0
      };
      console.log(msg);
      this.ws.send(JSON.stringify(msg));
    } else {
      this.callbackError({message: "会话已中止！"});
    }
  },
  formatDate: function (timstamp, fmt = 'yyyy-MM-dd hh:mm:ss') {
    let date = new Date();
    date.setTime(parseInt(timstamp) * 1000);
    if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
    }
    let o = {
      'M+': date.getMonth() + 1,
      'd+': date.getDate(),
      'h+': date.getHours(),
      'm+': date.getMinutes(),
      's+': date.getSeconds()
    };
    for (let k in o) {
      if (new RegExp(`(${k})`).test(fmt)) {
        let str = o[k] + '';
        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : this.padLeftZero(str));
      }
    }
    return fmt;
  },
  padLeftZero: function (str) {
    return ('00' + str).substr(str.length);
  },
  knowledges: function (keyword, page, limit, callback) {
    this.ajax_post_json_request({
      method: 'knowledges',
      agentId: this.my().agentId,
      page: page,
      keyword: keyword,
      limit: limit,
      token: this.token
    }, callback);
  },
  history: function (to, page, limit, lastMsgId, keyword, callback) {
    this.ajax_post_json_request({
      method: 'historyUserMessages',
      from: this.my().userId,
      targetUserId: to,
      lastMsgId: lastMsgId ? lastMsgId : 0,
      keyword: keyword || '',
      page: page,
      limit: limit,
      token: this.token
    }, callback);
  },
  chatToRobot: function (message, callback) {
    this.ajax_post_json_request({
      method: 'chatToRobot2',
      cvaId: this.cva.cvaId,
      message: message,
      type: 'desktop',
      token: this.token
    }, callback);
  },
  connectToHuman: function (callback) {
    this.ajax_post_json_request({
      method: 'toHuman',
      token: this.token
    }, (json) => {
      if (json.status) {
        this.server = json.data.wss;
        this.cva = json.data.cva;
        this.doConnect();
      } else if (407 === json.code) {
        this.doConnect();
      }
      if (callback) callback(json);
    });
  },
  takeCustomer: function (targetUserId, callback) {
    this.ajax_post_json_request({
      method: 'takeCustomer',
      targetUserId: targetUserId,
      token: this.token
    }, callback)
  },
  takeWaitingCustomers: function (callback) {
    this.ajax_post_json_request({
      method: 'takeWaitingCustomers',
      token: this.token
    }, callback);
  },
  historyUsers: function (page, limit, callback) {
    this.ajax_post_json_request({
      method: 'historyUsers',
      customerServiceId: this.my().userId,
      page: page,
      limit: limit,
      token: this.token
    }, callback);
  },
  /**
   * 主动关闭会话
   * @param cvaId 会话ID
   * @param callback
   */
  closeCva: function (cvaId, callback) {
    this.ajax_post_json_request({
      method: 'closeCva',
      cvaId: cvaId ? cvaId : this.cva.cvaId,
      token: this.token
    }, (json) => {
      this.close();
      if (callback) callback(json);
    });
  },
  /**
   * 转接
   * @param cvaId 会话ID
   * @param csId 转接客服ID
   * @param callback
   */
  transferCva: function (cvaId, csId, callback) {
    this.ajax_post_json_request({
      method: 'transferCva',
      cvaId: cvaId,
      csId: csId,
      token: this.token
    }, callback)
  },
  /**
   * 会话小结
   * @param cvaId
   * @param review
   * @param callback
   */
  reviewCva: function (cvaId, review, callback) {
    this.ajax_post_json_request({
      method: 'reviewCva',
      cvaId: cvaId,
      review: review,
      token: this.token
    }, callback)
  },
  /**
   * 会话评分
   * @param cvaId 会话ID
   * @param resolved 是否解决
   * @param score 评分，默认传0
   * @param userComment 用户文字评价
   * @param callback
   */
  scoreCva: function (cvaId, resolved, score, userComment, callback) {
    this.ajax_post_json_request({
      method: 'scoreCva',
      cvaId: cvaId ? cvaId : this.cva.cvaId,
      resolved: resolved,
      score: score,
      userComment: userComment,
      token: this.token
    }, callback)
  },
  /**
   * 获取在线客服
   * @param callback
   */
  onlineCs: function (callback) {
    this.ajax_post_json_request({
      method: 'onlineCs',
      token: this.token
    }, callback)
  },
  /**
   * 改变客服在线状态
   * @param status in ['online','busy','offline']
   * @param callback
   */
  csOnlineStatus: function (status, callback) {
    this.ajax_post_json_request({
      method: 'csOnlineStatus',
      status: status,
      token: this.token
    }, callback)
  },
  ajax_post_json_request: function (data, success_function_handle, error_function_handle) {
    this.post(this.getApiUrl(data.method), data, success_function_handle, error_function_handle);
  },
  post: function (url, data, success_function_handle, error_function_handle) {
    let xhr = new XMLHttpRequest();
    let formData = new FormData();
    for (let key in data) {
      formData.append(key, data[key]);
    }
    formData.append("version", "1.0");
    xhr.open("post", url);
    xhr.send(formData);
    xhr.onreadystatechange = function () {
      if (xhr.status === 200) {
        if (xhr.readyState === 4) {
          let responseData = JSON.parse(xhr.responseText);
          if (success_function_handle) success_function_handle(responseData);
        }
      } else {
        if (error_function_handle) {
          let responseData = JSON.parse(xhr.responseText);
          if (error_function_handle) error_function_handle(responseData);
        } else {
          alert("网络通信异常！" + xhr.responseText);
        }
      }
    };
  },
  messageConvert: function (serverMsg) {
    return {
      id: serverMsg.id,
      from: serverMsg.from,
      fromUser: serverMsg.fromUser,
      to: serverMsg.to ? serverMsg.to : chat.my().userId,
      toUser: serverMsg.toUser ? serverMsg.toUser : chat.my(),
      content: serverMsg.content,
      type: serverMsg.type,
      event: serverMsg.event,
      timestamp: chat.formatDate(serverMsg.timestamp, "yyyy-MM-dd hh:mm:ss")
    };
  }
};
Array.prototype.contains = function (obj) {
  let len = this.length;
  while (len--) {
    if (this[len] === obj) {
      return true
    }
  }
  return false;
};
Object.isNullOrUndefined = function (obj) {
  return typeof (obj) === "undefined" || obj == null
    || obj.toString().length === 0;
};
export default chat;

